package com.xiyuan;

/**
 * the description for class TestReflect
 *
 * @author xiyuan-lgz 2025-06-11 @version v1.0.0 新建与整理
 */

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Systems;
import com.xiyuan.smartutils.function.SFunc0;
import com.xiyuan.smartutils.reflect.Unsafe;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
// import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;

/**
 * the description for class ReflectTest
 *
 * @author xiyuan-lgz 2025-03-14 @version v1.0.0 新建与整理
 */
public class TestReflect {
    
    private static <T> void test(String name, int count, T target, SFunc0<T> consumer) {
        count = Math.max(count, 1);
        long t1 = System.nanoTime();
        for (int i = 0; i < count; i++) {
            try {
                consumer.apply();
            }
            catch (Exception e) {
            
            }
        }
        double ns = System.nanoTime() - t1 * 1.0;
        
        double us = ns / 1000;
        double ms = us / 1000;
        
        System.out.println(count + "===============" + name);
        System.out.print(StrUtils.rpad("ms:" + (((int) (ms * 100)) / 100.0), 20, " "));
        System.out.print(StrUtils.rpad("us:" + (((int) (us * 100)) / 100.0), 20, " "));
        System.out.print(StrUtils.rpad("ns:" + (((int) (ns * 100)) / 100.0), 20, " "));
        System.out.println();
        System.out.println();
        
    }
    
    // @Test
    // --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/sun.misc=ALL-UNNAMED --add-opens=java.base/jdk.internal.access=ALL-UNNAMED --add-opens=java.base/jdk.internal.module=ALL-UNNAMED --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED --add-exports=java.base/java.lang=ALL-UNNAMED --add-exports=java.base/sun.misc=ALL-UNNAMED --add-exports=java.base/jdk.internal.access=ALL-UNNAMED --add-exports=java.base/jdk.internal.module=ALL-UNNAMED --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-exports=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED
    public static void main(String[] args) throws Throwable {
        //
        // Module baseModules = Object.class.getModule();
        // Module thisModules = Unsafe.class.getModule();
        // baseModules.addOpens("java.lang", thisModules);
        // sun.misc.Unsafe ssssss = get();
        // System.out.println("sdvdsvdsvdsvv" + ssssss);
        //
        System.out.println("============================ReflectTest----start");
        System.out.println(Systems.getJavaVersion());
        System.out.println(Systems.getVmInfo());
        System.out.println(Systems.JAVA_MAIN_VERSION);
        System.out.println(Systems.JAVA_MAIN_VERSION);
        System.out.println("============================ReflectTest----end");
        
        // Systems.addOpens("jdk.internal.misc", ReflectTest.class);
        Unsafe xunsafe = Unsafe.getUnsafe();
        System.out.println("============================ unsafe.getVersion:"+ xunsafe.getVersion());
        System.out.println("============================ unsafe.provider:"+ xunsafe.getUnsafeProvider());
        if (xunsafe != null) {
            System.out.println(xunsafe.getClass());
        }
        // addOpens("java.base",
        //          "java.lang",
        //          xunsafe.getClass().getModule());
        // addOpens("java.base",
        //          Unsafe.getJavaUnsafe().getClass().getPackage().getName(),
        //          xunsafe.getClass().getModule());
        
        int asaaaa = 0;
        if (asaaaa > 0) return;
        final int total = 10000_0000;
        
        AAA object = new AAA();
        Field field = object.getClass().getDeclaredField("age");
        field.setAccessible(true);
        
        // 创建特权 Lookup 对象
        MethodHandles.Lookup lookup = MethodHandles.lookup().in(object.getClass());
        final long offset = xunsafe.objectFieldOffset(field);
        System.out.println("fieldOffset:" + offset);
        
        MethodHandle methodHandle = lookup.unreflectGetter(field);
        // VarHandle varHandle = lookup.unreflectVarHandle(field);
        
        // jdk.internal.misc.Unsafe unsafe = (jdk.internal.misc.Unsafe) JavaUnsafe.getJavaUnsafe(Systems.JAVA_MAIN_VERSION);
        // 获取 Module 类的静态方法 "addOpens"
        
        
        test(xunsafe.getClass().getName(), 1, object, () -> {
            
            Object object1 = xunsafe.getObject(object, offset);
            System.out.println(object1);
            return null;
        });
        test(xunsafe.getClass().getName(), total, object, () -> xunsafe.getObject(object, offset));
        // System.out.println("==========================================sun.misc.Unsafe.get=======================" + unsafe.getInt(object, offset));
        // test(unsafe.getClass().getName(), total, object, () -> unsafe.getObject(object, offset));
        test("MethodHandle.get", total, object, () -> {
            try {
                methodHandle.invoke(object);
            }
            catch (Throwable e) {
            }
            
            return null;
        });
        // test("VarHandle.get", total, object, () -> varHandle.get(object));
        // test("reflect.getInt", total, object, () -> field.getInt(object));
        
        
        System.out.println();
        //
        // /// //////////////////////////
        // test("getJavaUnsafe", total, object, () -> Unsafe.getJavaUnsafe());
        // test("getInt", total, object, () -> Unsafe.getUnsafe().getInt(object, finalAddr));
        // System.out.println(Unsafe.getUnsafe().getObject(object, finalAddr));
        // test("getObject", total, object, () -> Unsafe.getUnsafe().getObject(object, finalAddr));
        
        
        // Object ss = sun.misc.Unsafe.getUnsafe().getObject(object, addr);
        // System.out.println(ss);
        // Class<?> modulesClass = Class.forName("jdk.internal.module.Modules");
        // Method addOpens = modulesClass.getDeclaredMethod("addOpens", Module.class, String.class);
        // addOpens.setAccessible(true);
        // addOpens.invoke(null, "java.base", "jdk.internal.misc");
        //
        // System.out.println(Systems.getJavaVersion());
        //
        // System.out.println(Systems.JVM_VERSION);
        // // Systems.
        
        //
        // // Systems.addOpens(cla,ReflectTest.class);
        // Field theUnsafe = cla.getDeclaredField("theUnsafe");
        // MethodHandles.Lookup lop = MethodHandles.lookup();
        
        
        // MethodHandles.class.getConstructors()[0].newInstance();
        // MethodHandles.lookup();
        // MethodHandle handle =lop.unreflectGetter(theUnsafe);
        // // handle.bindTo()
        // sun.misc.Unsafe.getUnsafe().objectFieldOffset(theUnsafe);
        // sun.misc.Unsafe.getUnsafe().arrayBaseOffset();
        // sun.misc.Unsafe.getUnsafe().allocateInstance()
        // lop.unreflectConstructor();
        // handle.invoke();
        // theUnsafe.setAccessible(true);
        // System.out.println("Unsafe:" + theUnsafe.get(null));
        //
        // AAA aaa = new AAA();
        // BBB bbb = new BBB();
        // ReflectField reflectField1 = new ReflectField(AAA.class.getDeclaredField("age"));
        // ReflectField reflectField2 = reflectField1.bind(aaa);
        // Field field = reflectField2.getField();
        // long fieldOffset = reflectField2.getOffset();
        // long time = 0, end = 0;
        //
        // Reflect.setObjectValue(aaa, fieldOffset, null);
        // Reflect.getInt(aaa, fieldOffset);
        // System.out.println(Reflect.getInt(aaa, fieldOffset));
        // System.out.println(Reflect.getObjectValue(aaa, fieldOffset));
        
        // int total = 1000_000_000;
        // time = System.currentTimeMillis();
        // for (int i = 0; i < total; i++) {
        //     aaa.setAge(i);
        //     aaa.getAge();
        // }
        // end = System.currentTimeMillis();
        // System.out.println("obj.set(i) :" + (end - time));
        //
        // time = System.currentTimeMillis();
        // for (int i = 0; i < total; i++) {
        //     Reflect.setInt(aaa, fieldOffset,i);
        //     Reflect.getInt(aaa, fieldOffset);
        // }
        // end = System.currentTimeMillis();
        // System.out.println("Reflect.UNSAFE.set(i) :" + (end - time));
        
        // time = System.currentTimeMillis();
        // for (int i = 0; i < total; i++) {
        //     reflectField1.set(aaa, i);
        //     reflectField1.get(aaa);
        // }
        // end = System.currentTimeMillis();
        // System.out.println("MethodHandle.set(aaa, i) :" + (end - time));
        //
        // time = System.currentTimeMillis();
        // for (int i = 0; i < total; i++) {
        //     reflectField2.set(i);
        //     reflectField2.get(aaa);
        // }
        // end = System.currentTimeMillis();
        // System.out.println("MethodHandle.bindTo.set( i) :" + (end - time));
        //
        // //
        // time = System.currentTimeMillis();
        // for (int i = 0; i < total; i++) {
        //     reflectField2.getField().set(aaa, i);
        //     reflectField2.getField().get(aaa);
        // }
        // end = System.currentTimeMillis();
        // System.out.println("Field.set( i) :" + (end - time));
        
        
        // time = System.currentTimeMillis();
        // for (int i = 0; i < total; i++) {
        //     reflectField2.setValue(aaa, i);
        //     reflectField2.getValue(aaa);
        // }
        // end = System.currentTimeMillis();
        // System.out.println("Unsafe.set( i) :" + (end - time));
        // float t = reflectField2.getValue(aaa);
        
        // MethodHandles.privateLookupIn(Unsafe.class, MethodHandles.lookup());
        
    }
    
    
    static class AAA {
        private int[] age = {500};
        private String name;
        private boolean gender;
        private List<HashMap<String, AAA>> ss;
        
        // public int getAge() {
        //
        //     // System.out.println("setAge =>>:" + age);
        //     return age;
        //
        // }
        //
        // public void setAge(Integer age) {
        //     this.age = age;
        //     // System.out.println("setAge <<=:" + age);
        // }
        
        public String getName() {
            // System.out.println("getName=>>:" + name);
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
            System.out.println("getName<<=:" + name);
        }
        
        @Override
        public String toString() {
            return "AAA{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    ", gender='" + gender + '\'' +
                    '}';
        }
    }
    
    static class BBB extends AAA {
    }
}
